﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace EasyTrader.Signal
{
    public class BarSignalManager : EasyTrader.Signal.SignalManager
    {
        public BarSignalManager()
            : base()
        {
        }

        public override int GetSignal(int a_DataCount)
        {
            int signalVal = GlobalVar.SignalNone;

            return signalVal;
        }

        // 봉하나에서만 발생하는 신호
        // 이 신호는 막대가 일정 분량 이상의 거래량을 가지고 시가와 종가가 
        // 막대 전체 높이의 3/1이상으로 쏠려있을 때 발생한다.
        public int FindSummitSignal(int a_DataCount, EasyTrader.DataSet.ETDataTable a_DataTable, int a_MinVolume)
        {
            int signalVal = GlobalVar.SignalNone;
            if (a_DataCount <= 0)
                return signalVal;

            int rowCount = a_DataTable.GetRowCount();
            if (rowCount <= 0 || rowCount < a_DataCount)
                return signalVal;

            int curIndex = a_DataCount - 1;
            DataRow curRow = a_DataTable.Rows[curIndex];

            if (curRow == null)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["고가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["저가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["시가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["종가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["거래량"] == DBNull.Value)
                return signalVal;

            double high = Convert.ToDouble(curRow["고가"]);
            double low = Convert.ToDouble(curRow["저가"]);
            double open = Convert.ToDouble(curRow["시가"]);
            double close = Convert.ToDouble(curRow["종가"]);
            int volume = Convert.ToInt32(curRow["거래량"]);
            double barHeight = Math.Abs(close - open);
            if (barHeight < GlobalVar.MinBarHeight)
                return signalVal;

            if (volume < a_MinVolume)
                return signalVal;


            // 극단적인 망치의 형태를 취할 때 
            if (close > open) // 양봉일 때
            {
                double headHeight = Math.Abs(high - open);
                if (headHeight >= (barHeight / 3))
                {
                    signalVal = GlobalVar.SignalBuy;
                }
            }
            else // 음봉일 때
            {
                double headHeight = Math.Abs(low - open);
                if (headHeight >= (barHeight / 3))
                {
                    signalVal = GlobalVar.SignalSell;
                }
            }
            return signalVal;
        }

        // 봉이후 일정한 시간에 발생하는 신호
        // 이 신호는 막대가 일정 분량 이상의 거래량을 가지고 
        // 대량 거래가 발생한 봉을 완전히 잠식했을 때 신호를 낸다.
        // 양봉일 때는 매도 신호를 음봉일 때는 매수 신호를 낸다.
        public int FindVariationSignal(int a_DataCount, EasyTrader.DataSet.ETDataTable a_DataTable, int a_MinVolume)
        {
            int signalVal = GlobalVar.SignalNone;
            if (a_DataCount <= 2)
                return signalVal;

            int rowCount = a_DataTable.GetRowCount();
            if (rowCount <= 0 || rowCount < a_DataCount)
                return signalVal;

            int curIndex = a_DataCount - 1;
            DataRow curRow = a_DataTable.Rows[curIndex];

            if (curRow == null)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["고가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["저가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["시가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["종가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["거래량"] == DBNull.Value)
                return signalVal;

            int volume = 0;
            double high = 0;
            double low = 0;
            double open = 0;
            double close = 0;
            double bigHigh = 0;
            double bigLow = 0;
            int count = Math.Min(a_DataCount, 5);
            bool bigVolume = false;
            for (int i = a_DataCount - count, j = 0; j < count; j++, i++)
            {
                DataRow row = a_DataTable.Rows[i];
                volume = Convert.ToInt32(row["거래량"]);
                high = Convert.ToDouble(row["고가"]);
                low = Convert.ToDouble(row["저가"]);
                open = Convert.ToDouble(row["시가"]);
                close = Convert.ToDouble(row["종가"]);

                if (volume >= a_MinVolume)
                {
                    bigVolume = true;
                    bigHigh = high;
                    bigLow = low;
                    break;
                }
            }
            if (bigVolume == false)
                return signalVal;

            high = Convert.ToDouble(curRow["고가"]);
            low = Convert.ToDouble(curRow["저가"]);
            open = Convert.ToDouble(curRow["시가"]);
            close = Convert.ToDouble(curRow["종가"]);

            double barHeight = Math.Abs(high - low);
            if (barHeight < GlobalVar.MinBarHeight)
                return signalVal;

            if (close > open) // 양봉 일 때
            {
                // 큰 양봉의 저가까지 내려왔을 때 발생하는 신호
                if (close <= bigLow)
                {
                    signalVal = GlobalVar.SignalSell;
                }
            }
            else if (close < open)
            {
                // 큰 음봉의 고가까지 올라왔을 때 발생하는 신호
                if (close >= bigHigh)
                {
                    signalVal = GlobalVar.SignalBuy;
                }
            }
            return signalVal;
        }


        // 봉이후 일정한 시간에 발생하는 신호
        // 이 신호는 막대가 일정 분량 이상의 거래량을 가지고 
        // 그 다음봉도 같은 봉이고 
        // 대량 거래가 발생한 봉을 완전히 잠식했을 때 신호를 낸다.
        // 양봉일 때는 매도 신호를 음봉일 때는 매수 신호를 낸다.
        public int FindSummitVariationSignal(int a_DataCount, EasyTrader.DataSet.ETDataTable a_DataTable, int a_MinVolume)
        {
            int signalVal = GlobalVar.SignalNone;
            if (a_DataCount <= 2)
                return signalVal;

            int rowCount = a_DataTable.GetRowCount();
            if (rowCount <= 0 || rowCount < a_DataCount)
                return signalVal;

            int curIndex = a_DataCount - 1;
            DataRow curRow = a_DataTable.Rows[curIndex];

            if (curRow == null)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["고가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["저가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["시가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["종가"] == DBNull.Value)
                return signalVal;
            // 값이 없을 경우는 넘어 간다.
            if (curRow["거래량"] == DBNull.Value)
                return signalVal;

            int volume = 0;
            double high = 0;
            double low = 0;
            double open = 0;
            double close = 0;
            double bigHigh = 0;
            double bigLow = 0;
            int count = Math.Min(a_DataCount, 5);
            bool bigVolume = false;
            for (int i = a_DataCount - count, j = 0; j < count; j++, i++)
            {
                DataRow row = a_DataTable.Rows[i];
                volume = Convert.ToInt32(row["거래량"]);
                high = Convert.ToDouble(row["고가"]);
                low = Convert.ToDouble(row["저가"]);
                open = Convert.ToDouble(row["시가"]);
                close = Convert.ToDouble(row["종가"]);
                if (volume >= a_MinVolume)
                {
                    bigVolume = true;
                    bigHigh = high;
                    bigLow = low;

                    int barType = 0;
                    if (close > open)
                        barType = 1;
                    else if (close < open)
                        barType = -1;

                    if (i + 1 <= a_DataCount - 1)
                    {
                        row = a_DataTable.Rows[i + 1];
                        volume = Convert.ToInt32(row["거래량"]);
                        high = Convert.ToDouble(row["고가"]);
                        low = Convert.ToDouble(row["저가"]);
                        open = Convert.ToDouble(row["시가"]);
                        close = Convert.ToDouble(row["종가"]);
                        // 대량 거래가 발생한 봉과 그 다음 봉이 같은 방향일 때
                        if (barType > 0 && close > open)
                        {
                            bigVolume = true;
                            break;
                        }

                        if (barType < 0 && close < open)
                        {
                            bigVolume = true;
                            break;
                        }
                    }
                }
            }

            if (bigVolume == false)
                return signalVal;

            high = Convert.ToDouble(curRow["고가"]);
            low = Convert.ToDouble(curRow["저가"]);
            open = Convert.ToDouble(curRow["시가"]);
            close = Convert.ToDouble(curRow["종가"]);

            double barHeight = Math.Abs(high - low);
            if (barHeight < GlobalVar.MinBarHeight)
                return signalVal;

            if (close > open) // 양봉 일 때
            {
                // 큰 양봉의 저가까지 내려왔을 때 발생하는 신호
                if (close <= bigLow)
                {
                    signalVal = GlobalVar.SignalSell;
                }
            }
            else if (close < open)
            {
                // 큰 음봉의 고가까지 올라왔을 때 발생하는 신호
                if (close >= bigHigh)
                {
                    signalVal = GlobalVar.SignalBuy;
                }
            }
            return signalVal;
        }
    }
}
